#ifndef TYPES_H
#define TYPES_H

#include <memory>
#include <string>
#include <vector>
#include <set>

// 表示一个内存区间 [start, end)
struct Interval
{
    Interval(unsigned long long start = 0, unsigned long long end = 0, void * user = NULL) : start(start), end(end), user(user)
    {}
    unsigned long long start;
    unsigned long long end;
    void * user;

    // 为了在 set 或 map 中使用，需要定义比较操作
    bool operator<(const Interval & other) const
    {
        if (start != other.start) {
            return start < other.start;
        }
        return end < other.end;
    }
};

struct MemBlock
{
    MemBlock(unsigned long long addrBegin, unsigned long long addrEnd, unsigned timeStart = 0, unsigned timeDuration = 0) : addrBegin(addrBegin), addrEnd(addrEnd), timeStart(timeStart), timeDuration(timeDuration), needReserve(false)
    {}
    bool inter(const MemBlock & other)
    {
        return std::max(addrBegin, other.addrBegin) < std::min(addrEnd, other.addrEnd);
    }
    bool contain(const MemBlock & other)
    {
        return addrBegin <= other.addrBegin && addrEnd >= other.addrEnd;
    }
    unsigned long long addrBegin;
    unsigned long long addrEnd;
    unsigned long long timeStart;
    unsigned long long timeDuration;
    std::vector<std::shared_ptr<MemBlock>> nextUseBlock;
    bool needReserve;
    bool needRecord;
    unsigned record;
};

inline bool operator<(std::shared_ptr<MemBlock> & p1, std::shared_ptr<MemBlock> & p2)
{
    return p1->addrBegin < p2->addrBegin;
}

struct Task
{
    Task() : timeStart(0), timeLen(0)
    {}
    std::set<std::shared_ptr<MemBlock>> memSet;
    unsigned long long timeStart;
    unsigned long long timeLen;
};

// 表示一个输入的内存访问请求
struct Access
{
    Access(int id = 0, long long addr = 0, long long size = 0, long long timeStart = 0, long long timeDuration = 0) : id(id), addr(addr), size(size), timeStart(timeStart), timeDuration(timeDuration)
    {}
    int id;
    unsigned long long addr;
    unsigned long long size;
    unsigned long long timeStart;    // 最早可开始时间
    unsigned long long timeDuration; // 访问持续时间

    // 辅助函数，获取该访问对应的内存区间
    Interval getInterval() const
    {
        return Interval(addr, addr + size);
    }
};

// 表示一个输出的操作指令
struct Operation
{
    std::string type;        // "Reload", "Offload", "Visit", "Fin"
    unsigned long long time; // 操作开始的时刻
    unsigned long long arg1; // 参数1 (地址 或 访问ID)
    unsigned long long arg2; // 参数2 (大小)

    // 为了按时间排序
    bool operator<(const Operation & other) const
    {
        static char typeSort[26] = {0};
        if (typeSort[0] == 0) {
            typeSort['V' - 'A'] = 1;
            typeSort['R' - 'A'] = 2;
            typeSort['O' - 'A'] = 3;
            typeSort['F' - 'A'] = 4;
        }
        if (time != other.time) {
            return time < other.time;
        }
        return typeSort[type.at(0) - 'A'] < typeSort[other.type.at(0) - 'A'];
    }
};

#endif // TYPES_H
